﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Client.App.Properties;
using Core.Mvvm;

namespace Client.App.Services
{
    public sealed class ConfigurationService : IConfigurationService
    {
        #region Fields

        private static readonly Lazy<ConfigurationService> Lazy =
            new Lazy<ConfigurationService>(() => new ConfigurationService());

        #endregion

        #region Properties

        public static ConfigurationService Instance
        {
            get { return Lazy.Value; }
        }

        #endregion

        #region Events

        public event EventHandler<ParametrizedEventArgs<Type>> ProcessingBlockTypeChanged;
        public event EventHandler<ParametrizedEventArgs<int>> MaxProcessingBlockSizeChanged;
        public event EventHandler<ParametrizedEventArgs<int>> AttemptCountChanged;

        #endregion

        #region Constructors

        private ConfigurationService()
        {

        }

        #endregion

        #region Methods

        public int GetMaxProcessingBlockSize()
        {
            return Settings.Default.MaxProcessingBlockSize;
        }

        public void SetMaxProcessingBlockSize(int maxProcessingBlockSize)
        {
            Settings.Default.MaxProcessingBlockSize = maxProcessingBlockSize;
            Settings.Default.Save();
            OnMaxProcessingBlockSizeChanged(maxProcessingBlockSize);
        }

        public Type GetProcessingBlockType()
        {
            return Type.GetType(Settings.Default.ProcessingBlockType);
        }

        public void SetProcessingBlockType(Type type)
        {
            Settings.Default.ProcessingBlockType = type.AssemblyQualifiedName;
            Settings.Default.Save();
            OnProcessingBlockTypeChanged(type);
        }

        public int GetAttemptCount()
        {
            return Settings.Default.AttemptCount;
        }

        public void SetAttemptCount(int attemptCount)
        {
            Settings.Default.AttemptCount = attemptCount;
            Settings.Default.Save();
            OnAttemptCountChanged(attemptCount);
        }
        
        private void OnProcessingBlockTypeChanged(Type type)
        {
            var handler = Interlocked.CompareExchange(ref ProcessingBlockTypeChanged, null, null);
            if (!ReferenceEquals(handler, null))
            {
                handler(this, new ParametrizedEventArgs<Type>(type));
            }
        }

        private void OnMaxProcessingBlockSizeChanged(int size)
        {
            var handler = Interlocked.CompareExchange(ref MaxProcessingBlockSizeChanged, null, null);
            if (!ReferenceEquals(handler, null))
            {
                handler(this, new ParametrizedEventArgs<int>(size));
            }
        }

        private void OnAttemptCountChanged(int attemptCount)
        {
            var handler = Interlocked.CompareExchange(ref AttemptCountChanged, null, null);
            if (!ReferenceEquals(handler, null))
            {
                handler(this, new ParametrizedEventArgs<int>(attemptCount));
            }
        }

        #endregion

    }
}
